﻿#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<list>
#include<utility>
#include"list.h"
#include"string.h"
using namespace std;

//template <class ...Args>
//void Print(Args&&... args)
//{
//	cout << sizeof...(args) << endl;
//} 
//void test1()
//{
//	double x = 2.2;
//	Print(); // 包⾥有0个参数
//	Print(1); // 包⾥有1个参数
//	Print(1, string("xxxxx")); // 包⾥有2个参数
//	Print(1.1, string("xxxxx"), x); // 包⾥有3个参数
//}
//// 原理1：编译本质这⾥会结合引⽤折叠规则实例化出以下四个函数
//void Print();
//void Print(int&& arg1);
//void Print(int&& arg1, string&& arg2);
//void Print(double&& arg1, string&& arg2, double& arg3);
//// 原理2：更本质去看没有可变参数模板，我们实现出这样的多个函数模板才能⽀持
//// 这⾥的功能，有了可变参数模板，我们进⼀步被解放，
//// 他是类型泛化基础上叠加数量变化，让我们泛型编程更灵活。
//void Print();
//template <class T1>
//void Print(T1&& arg1);
//template <class T1, class T2>
//void Print(T1&& arg1, T2&& arg2);
//template <class T1, class T2, class T3>
//void Print(T1&& arg1, T2&& arg2, T3&& arg3);
//// ...
//模板元编程
void showList()
{
	// 编译器时递归的终⽌条件，参数包是0个时，直接匹配这个函数
	cout <<endl;
}
template <class T1, class... Args>
void showList(T1&& x, Args&&... args)
{
	cout<<x<<endl;
	showList(args...);
}
template <class... Args>
// 编译时递归推导解析参数
void Print(Args... args)
{
	//args是N个参数的参数包
	//调用showList，参数包第一个传递给x
	//剩下N-1个参数传递给args
	showList(args...);
}
void test2()
{
	Print();
	Print(1);
	Print(1, string("xxxxx"));
	Print(1, string("xxxxx"), 2.2);
}
//示例2
template <class T>
const T& GetArg(const T& x)
{
	cout << x << " ";
	return x;
} 
template <class ...Args>
void Arguments(Args... args)
{
}
template <class ...Args>
void print(Args... args)
{
	// 注意GetArg必须返回或者到的对象，这样才能组成参数包给Arguments
	Arguments(GetArg(args)...);
}
// 本质可以理解为编译器编译时，包的扩展模式
// 将上⾯的函数模板扩展实例化为下⾯的函数
//void Print(int x, string y, double z)
//{
// Arguments(GetArg(x), GetArg(y), GetArg(z));
//}
void test3()
{
	print(1, string("xxxxx"), 2.2);
}
// emplace_back总体⽽⾔是更⾼效，推荐以后使⽤emplace系列替代insert和push系列
void test4()
{
	list<string_h::string> lt;
	// 传左值，跟push_back⼀样，⾛拷⻉构造
	string_h::string s1("111111111111");
	lt.emplace_back(s1);
	cout << "*********************************" << endl;
	// 右值，跟push_back⼀样，⾛移动构造
	lt.emplace_back(move(s1));
	cout << "*********************************" << endl;
	// 直接把构造string参数包往下传，直接⽤string参数包构造string
	// 这⾥达到的效果是push_back做不到的
	lt.emplace_back("111111111111");//构造
	//lt.push_back("111111111111");//构造+移动构造
	//lt.emplace_back(10,"x");//构造
	cout << "*********************************" << endl;
}
void test5()
{
	list<pair<string_h::string, int>> lt1;
	// 跟push_back⼀样
	// 构造pair + 拷⻉/移动构造pair到list的节点中data上
	pair<string_h::string, int> kv("苹果", 1);
	lt1.emplace_back(kv);
	cout << "*********************************" << endl;
	// 跟push_back⼀样
	lt1.emplace_back(move(kv));
	cout << "*********************************" << endl;
	////////////////////////////////////////////////////////////////////
	// 直接把构造pair参数包往下传，直接⽤pair参数包构造pair
	// 这⾥达到的效果是push_back做不到的
	lt1.emplace_back("苹果", 1);
	//lt1.emplace_back({ "苹果", 1 });//emplace不允许这样传值！

	cout << "*********************************" << endl;
}
namespace list_h
{
	void test_list1()
	{
		list<int> lt;
		lt.push_back(1);
		lt.push_back(2);
		lt.push_back(3);
		lt.push_back(4);

		list<int>::iterator it = lt.begin();
		while (it != lt.end())
		{
			*it += 10;
			cout << *it << " ";
			++it;
		}
		cout << endl;

		lt.push_front(1);
		lt.push_front(2);
		lt.push_front(3);
		lt.push_front(4);

		for (auto e : lt)
		{
			cout << e << " ";
		}
		cout << endl;

		lt.pop_back();
		lt.pop_back();
		lt.pop_front();
		lt.pop_front();

		for (auto e : lt)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void test_list2()
	{
		list<int> lt;
		lt.push_back(1);
		lt.push_back(2);
		lt.push_back(3);
		lt.push_back(4);

		list<int>::iterator it = lt.begin();
		while (it != lt.end())
		{
			if (*it % 2 == 0)
			{
				it = lt.erase(it);
			}
			else
			{
				++it;
			}
		}

		for (auto e : lt)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	// const T* p1;
	// T* const p2;
	void print(const list<int>& lt)
	{
		// const迭代器的要求不是本身不能修改，而是指向的内容不能修改
		//const list<int>::iterator it = lt.begin();
		list<int>::const_iterator it = lt.begin();
		while (it != lt.end())
		{
			// *it = 10;
			cout << *it << " ";
			++it;
		}
		cout << endl;
	}

	void test_list3()
	{
		list<int> lt1;
		lt1.push_back(1);
		lt1.push_back(2);
		lt1.push_back(3);
		lt1.push_back(4);

		for (auto e : lt1)
		{
			cout << e << " ";
		}
		cout << endl;

		list<int> lt2(lt1);

		for (auto e : lt2)
		{
			cout << e << " ";
		}
		cout << endl;

		list<int> lt3 = { 1,2,3,4,5,6 };
		lt1 = lt3;

		for (auto e : lt1)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	struct AA
	{
		int _a1;
		int _a2;

		AA(int a1 = 1, int a2 = 1)
			:_a1(a1)
			, _a2(a2)
		{
		}
	};

	//void test_list4()
	//{
	//	//AA aa1 = { 1,1 };
	//	vector<AA> v1;
	//	v1.push_back({ 1,1 });
	//	v1.push_back({ 2,2 });
	//	v1.push_back({ 3,3 });
	//	vector<AA>::iterator it1 = v1.begin();
	//	while (it1 != v1.end())
	//	{
	//		cout << it1->_a1<<":" <<it1->_a2<< endl;
	//		++it1;
	//	}
	//	cout << endl;

	//	list<AA> lt1;
	//	lt1.push_back({ 1,1 });
	//	lt1.push_back({ 2,2 });
	//	lt1.push_back({ 3,3 });
	//	list<AA>::iterator lit1 = lt1.begin();
	//	while (lit1 != lt1.end())
	//	{
	//		//cout << (*lit1)._a1 <<":"<< (*lit1)._a2 << endl;
	//		// 特殊处理，省略了一个->,为了可读性
	//		cout << lit1->_a1 << ":" << lit1->_a2 << endl;
	//		cout << lit1.operator->()->_a1 << ":" << lit1.operator->()->_a2 << endl;

	//		++lit1;
	//	}
	//	cout << endl;
	//}
}
int main()
{
	//test1();
	//test2();
	//test3();
	test4();
	test5();
	return 0;
}